Skip to content

fix: refine stability precedence to support standard prerelease sorting#6

Merged
joaopapereira merged 1 commit intocarvel-dev:masterfrom
sameerforge:topic/sameerforge/follow-up-semver-fix
Apr 13, 2026
Merged

fix: refine stability precedence to support standard prerelease sorting#6
joaopapereira merged 1 commit intocarvel-dev:masterfrom
sameerforge:topic/sameerforge/follow-up-semver-fix

Conversation

@sameerforge
Copy link
Copy Markdown

@sameerforge sameerforge commented Mar 31, 2026

Refinement of Metadata Precedence Logic
This follow-up PR adjusts the build metadata comparison logic to ensure stability-aware precedence (GA > RC) only applies when comparing numeric segments to alphanumeric ones.

Verified Improvements:
Natural Sorting: vmware.10-fips now correctly ranks higher than vmware.9-fips.

Stability: 3.4.0+v1.33 (Stable) now correctly ranks higher than 3.4.0+v1.33-rc.2.

Compatibility: Standard pre-release ordering (e.g., 0.0.1-pre.1 < 0.0.1-rc.0) is preserved, fixing a regression found in vendir.

Validation :
All 38+ existing unit tests, alongside new edge-case coverage Passed ✅

Current changeset Validation : 
➜  v4 git:(topic/sameerforge/follow-up-semver-fix) go test -v .                                                        
=== RUN   TestJSONMarshal
--- PASS: TestJSONMarshal (0.00s)
=== RUN   TestJSONUnmarshal
--- PASS: TestJSONUnmarshal (0.00s)
=== RUN   TestParseComparator
--- PASS: TestParseComparator (0.00s)
=== RUN   TestSplitAndTrim
--- PASS: TestSplitAndTrim (0.00s)
=== RUN   TestSplitComparatorVersion
--- PASS: TestSplitComparatorVersion (0.00s)
=== RUN   TestBuildVersionRange
--- PASS: TestBuildVersionRange (0.00s)
=== RUN   TestSplitORParts
--- PASS: TestSplitORParts (0.00s)
=== RUN   TestGetWildcardType
--- PASS: TestGetWildcardType (0.00s)
=== RUN   TestCreateVersionFromWildcard
--- PASS: TestCreateVersionFromWildcard (0.00s)
=== RUN   TestIncrementMajorVersion
--- PASS: TestIncrementMajorVersion (0.00s)
=== RUN   TestIncrementMinorVersion
--- PASS: TestIncrementMinorVersion (0.00s)
=== RUN   TestExpandWildcardVersion
--- PASS: TestExpandWildcardVersion (0.00s)
=== RUN   TestVersionRangeToRange
--- PASS: TestVersionRangeToRange (0.00s)
=== RUN   TestRangeAND
--- PASS: TestRangeAND (0.00s)
=== RUN   TestRangeOR
--- PASS: TestRangeOR (0.00s)
=== RUN   TestParseRange
--- PASS: TestParseRange (0.00s)
=== RUN   TestMustParseRange
--- PASS: TestMustParseRange (0.00s)
=== RUN   TestMustParseRange_panic
--- PASS: TestMustParseRange_panic (0.00s)
=== RUN   TestStringer
--- PASS: TestStringer (0.00s)
=== RUN   TestParse
--- PASS: TestParse (0.00s)
=== RUN   TestParseTolerant
--- PASS: TestParseTolerant (0.00s)
=== RUN   TestMustParse
--- PASS: TestMustParse (0.00s)
=== RUN   TestMustParse_panic
--- PASS: TestMustParse_panic (0.00s)
=== RUN   TestValidate
--- PASS: TestValidate (0.00s)
=== RUN   TestFinalizeVersionMethod
--- PASS: TestFinalizeVersionMethod (0.00s)
=== RUN   TestCompare
--- PASS: TestCompare (0.00s)
=== RUN   TestWrongFormat
--- PASS: TestWrongFormat (0.00s)
=== RUN   TestWrongTolerantFormat
--- PASS: TestWrongTolerantFormat (0.00s)
=== RUN   TestCompareHelper
--- PASS: TestCompareHelper (0.00s)
=== RUN   TestIncrements
--- PASS: TestIncrements (0.00s)
=== RUN   TestPreReleaseVersions
--- PASS: TestPreReleaseVersions (0.00s)
=== RUN   TestBuildMetaDataVersions
--- PASS: TestBuildMetaDataVersions (0.00s)
=== RUN   TestNewHelper
--- PASS: TestNewHelper (0.00s)
=== RUN   TestMakeHelper
--- PASS: TestMakeHelper (0.00s)
=== RUN   TestFinalizeVersion
--- PASS: TestFinalizeVersion (0.00s)
=== RUN   TestEdgeCases_NaturalSortAndMetadata
--- PASS: TestEdgeCases_NaturalSortAndMetadata (0.00s)
=== RUN   TestSort
--- PASS: TestSort (0.00s)
=== RUN   TestScanString
--- PASS: TestScanString (0.00s)
PASS
ok      github.com/carvel-dev/semver/v4 0.502s

Validation with Vendir Test :
Tests Passed ✅

➜  vendir git:(develop) ✗ go test -v ./pkg/vendir/versions/                                   

=== RUN   TestSemverOrder
--- PASS: TestSemverOrder (0.00s)
=== RUN   TestSemverFilter
--- PASS: TestSemverFilter (0.00s)
=== RUN   TestSemverWithoutPrereleases
--- PASS: TestSemverWithoutPrereleases (0.00s)
=== RUN   TestSemverWithPrereleases
--- PASS: TestSemverWithPrereleases (0.00s)
=== RUN   TestSemverWithPrereleaseIdentifiers
--- PASS: TestSemverWithPrereleaseIdentifiers (0.00s)
=== RUN   TestSemverWithBuildMetadata
--- PASS: TestSemverWithBuildMetadata (0.00s)
=== RUN   TestSemverWithBuildMetadataAndConstraint
--- PASS: TestSemverWithBuildMetadataAndConstraint (0.00s)
=== RUN   TestHighestVersionWithConstraints
--- PASS: TestHighestVersionWithConstraints (0.00s)
PASS
ok      carvel.dev/vendir/pkg/vendir/versions   (cached)

@sameerforge
Copy link
Copy Markdown
Author

@joaopapereira Please review this follow-up change for #5

1 similar comment
@sameerforge
Copy link
Copy Markdown
Author

@joaopapereira Please review this follow-up change for #5

Comment thread v4/semver.go Outdated
Comment thread v4/semver_test.go Outdated
Comment thread v4/semver_test.go Outdated
@sameerforge sameerforge force-pushed the topic/sameerforge/follow-up-semver-fix branch 3 times, most recently from 01fb27f to d3217c1 Compare April 7, 2026 05:32
@sameerforge
Copy link
Copy Markdown
Author

@joaopapereira Please review this follow-up change for #5

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refines the metadata comparison logic in the semver library to support stability-aware precedence (GA > RC) in build metadata while preserving standard pre-release ordering. The changes focus on the versionExtension.Compare method, which now only applies stability-aware precedence when comparing numeric segments with alphanumeric segments containing pre-release markers (like "rc", "beta", etc.), rather than applying this logic uniformly to all string-vs-string comparisons.

Changes:

  • Refined isPreReleaseLabel function to require both a hyphen and a pre-release marker (alpha, beta, rc, pre, dev) to identify pre-release segments in numeric vs alphanumeric comparisons
  • Removed the string-vs-string pre-release comparison logic that was causing standard pre-release ordering (e.g., pre < rc) to be incorrectly evaluated
  • Added four new test cases covering edge cases: vendir compatibility, numeric pre-release ordering, and natural sorting with build metadata

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
v4/semver.go Refined the isPreReleaseLabel function to implement stability-aware precedence only for numeric vs alphanumeric comparisons, and removed problematic string-vs-string pre-release logic
v4/semver_test.go Added four new edge-case test cases covering vendir compatibility, pre-release ordering, and natural sorting with build metadata

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread v4/semver.go Outdated
Signed-off-by: Sameer <sameer.khan@broadcom.com>
@sameerforge sameerforge force-pushed the topic/sameerforge/follow-up-semver-fix branch from d3217c1 to 750a47e Compare April 8, 2026 06:16
@sameerforge sameerforge requested a review from Copilot April 8, 2026 06:17
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sameerforge
Copy link
Copy Markdown
Author

@joaopapereira PR is ready for your review now.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

v4/semver.go:510

  • The logic for comparing alphanumeric segments no longer includes stability-aware precedence for pre-release markers. This breaks test case "3.4.0+v1.33-rc.2" vs "3.4.0+v1.33", where the build metadata segment "v1.33-rc" should be less than "v1.33" (GA should rank higher than RC). However, with the current code, naturalLess("v1.33-rc", "v1.33") returns false because "v1.33-rc" has more chunks than "v1.33" after the common prefix ["v", "1", ".", "33"], causing the comparison to return 1 instead of -1. The removed string-vs-string pre-release marker comparison needs to be reintroduced for alphanumeric segments containing pre-release identifiers, or the test expectation needs to be updated to reflect that RC is now considered greater than GA in build metadata.
	if v.IsNum && !o.IsNum {
		if isPreReleaseLabel(o.VersionStr) {
			return 1 // Number wins against an RC/Alpha/Beta string
		}
		return -1 // Standard SemVer: Number < String
	}
	if !v.IsNum && o.IsNum {
		if isPreReleaseLabel(v.VersionStr) {
			return -1 // RC/Alpha/Beta string loses against a Number
		}
		return 1 // Standard SemVer: String > Number
	}

	// 3. Both are Alphanumeric
	if v.VersionStr == o.VersionStr {
		return 0
	}

	// Natural sort fallback for generic segments (e.g. "9-fips" vs "10-fips")
	if naturalLess(v.VersionStr, o.VersionStr) {
		return -1
	}
	return 1

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@sameerforge
Copy link
Copy Markdown
Author

sameerforge commented Apr 9, 2026

Comments suppressed due to low confidence (1)
v4/semver.go:510

  • The logic for comparing alphanumeric segments no longer includes stability-aware precedence for pre-release markers. This breaks test case "3.4.0+v1.33-rc.2" vs "3.4.0+v1.33", where the build metadata segment "v1.33-rc" should be less than "v1.33" (GA should rank higher than RC). However, with the current code, naturalLess("v1.33-rc", "v1.33") returns false because "v1.33-rc" has more chunks than "v1.33" after the common prefix ["v", "1", ".", "33"], causing the comparison to return 1 instead of -1. The removed string-vs-string pre-release marker comparison needs to be reintroduced for alphanumeric segments containing pre-release identifiers, or the test expectation needs to be updated to reflect that RC is now considered greater than GA in build metadata.

All the Tests are passing as expected, along with the mentioned test case "3.4.0+v1.33-rc.2" vs "3.4.0+v1.33". The stability logic correctly prioritizes GA over RC before the natural sort fallback; this appears to be an AI false positive.

@sameerforge
Copy link
Copy Markdown
Author

@joaopapereira Please review the final changes.

@sameerforge
Copy link
Copy Markdown
Author

@joaopapereira Please review the changes.

@sameerforge
Copy link
Copy Markdown
Author

@joaopapereira Please review the changes.

Copy link
Copy Markdown
Member

@joaopapereira joaopapereira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@joaopapereira joaopapereira merged commit f136b2e into carvel-dev:master Apr 13, 2026
10 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants